#! /usr/bin/python3

import argparse
import itertools
import sys

from shared.gameState import GameState
from maze.mazemaker import DepthFirstGenerator
import ui

BEST_UIS = [
    'PygameUI',
    'TkinterUI',
    'CursesUI'
]


class Game:
    def __init__(self, generator=None, ui_name="_BEST", enemies=None):
        # self.mazeGenerator = mazeGenerator

        # self.maze = self.mazeGenerator.generate()
        self.ui = None
        self.maze = None
        self.state = None
        self.load_maze(DepthFirstGenerator(16, 16))

        if ui_name == "_BEST":
            # Use UIs from best to worst.
            for ui_type in BEST_UIS:
                if self._try_ui(ui_type):
                    break
            else:
                raise RuntimeError('No usable UIs.')
        else:
            # Use requested UI if possible; otherwise error.
            if not self._try_ui(ui_name):
                raise RuntimeError('No usable UIs.')

    def load_maze(self, maze):
        self.maze = maze
        self.state = GameState(self.maze)
        if self.ui is not None:
            self.ui.update(self.state)

    def _try_ui(self, ui_name):
        if ui_name in ui.AVAILABLE:
            self.ui = ui.AVAILABLE[ui_name](self.state)
            return True
        else:
            return False

    def step(self):
        user_inputs = self.ui.poll()
        ai_inputs = []

        if self.state.condition == "running":
            for enemy in self.state.enemies:
                event = enemy.move()
                if event is not None:
                    ai_inputs.append(event)

            self.state.do_moves()

            self.state.checkWinLoss()

        inputs = itertools.chain(user_inputs, ai_inputs)
        for input_ in inputs:
            self._handle_input(input_)
        self.ui.update(self.state)
        self.ui.draw()

        # Wait for next frame.
        self.ui.wait()

    def restart(self):
        self.load_maze(DepthFirstGenerator(16, 16))

    def _handle_input(self, input_):
        if input_.action == "QUIT":
            sys.exit(0)
        elif input_.action == "RESTART":
            self.restart()
        elif hasattr(input_, 'entity'):
            # Event affects an entity.
            entity = input_.entity
            entity.process_event(input_)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Process command-line arguments.')
    parser.add_argument('--ui', dest='ui', default='_BEST')

    game = Game(ui_name=parser.parse_args().ui)

    while True:
        game.step()
